package org.jeecg.interceptor;


import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.annotation.ApiLogin;
import org.jeecg.com.util.ThirdSessionHolder;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.TenantContextHolder;
import org.jeecg.modules.wxuser.dto.ThirdSession;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * ThirdSession拦截器，校验每个请求的ThirdSession
 * @author
 */
@Slf4j
//@AllArgsConstructor
@Component
public class ThirdSessionInterceptor implements HandlerInterceptor {
//public class ThirdSessionInterceptor extends HandlerInterceptorAdapter {
//	private final RedisTemplate redisTemplate;

	@Resource
	private RedisUtil redisUtil;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//		if (!(handler instanceof HandlerMethod)) {
//			return super.preHandle(request, response, handler);
//		}
		if ((handler instanceof HandlerMethod)) {
			HandlerMethod method = (HandlerMethod) handler;
			//判断访问的control是否添加ApiLogin注解
			ApiLogin apiLogin = method.getMethodAnnotation(ApiLogin.class);
			String appIdHeader = request.getHeader("app-id");
			//小程序端的所有接口需要登录才能访问，校验thirdSession
			return this.judeSession(request, response, apiLogin);
		}
		return Boolean.TRUE;
	}

	/**
	 * 校验session
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	private boolean judeSession(HttpServletRequest request, HttpServletResponse response, ApiLogin apiLogin) throws IOException {
		//获取header中的ThirdSession
		String thirdSessionHeader = request.getHeader("third-session");
		if (StrUtil.isNotBlank(thirdSessionHeader)) {
			//获取缓存中的ThirdSession
			String key = CommonConstant.PREFIX_WX_APP_USER_TOKEN + thirdSessionHeader;
			Object thirdSessionObj = redisUtil.get(key);
			if (thirdSessionObj == null) {//session过期
				ThirdSessionHolder.clear();
				this.writerPrint(response, "登录超时，请重新登录");
				return Boolean.FALSE;
			} else {
				String thirdSessionStr = String.valueOf(thirdSessionObj);
				ThirdSession thirdSession = JSONUtil.toBean(thirdSessionStr, ThirdSession.class);
				//判断session是否属于当前tenantId、appId
				String tenantIdHeader = request.getHeader("tenant-id");
				if (StrUtil.isNotBlank(tenantIdHeader) && !thirdSession.getTenantId().equals(tenantIdHeader)) {
					this.writerPrint(response, "登录超时，请重新登录");
					return Boolean.FALSE;
				}
				String appIdHeader = request.getHeader("app-id");
				if (StrUtil.isNotBlank(appIdHeader) && StrUtil.isNotBlank(thirdSession.getAppId()) && !thirdSession.getAppId().equals(appIdHeader)) {
					this.writerPrint(response, "登录超时，请重新登录");
					return Boolean.FALSE;
				}
				redisUtil.expire(key, JwtUtil.EXPIRE_TIME * 24 * 30 / 1000);//更新session过期时间
				TenantContextHolder.setTenantId(thirdSession.getTenantId());//设置租户ID
				ThirdSessionHolder.setThirdSession(thirdSession);//设置thirdSession

				if (apiLogin != null && apiLogin.mustLogin()) {
					//此接口必须登录商城才能访问
					return this.judeSessionUserMall(response, thirdSession);
				}
				return Boolean.TRUE;
			}
		} else {
			this.writerPrint(response, "session不能为空");
			return Boolean.FALSE;
		}
	}

	/**
	 * 校验session是否商城登录
	 * @param thirdSession
	 * @return
	 * @throws IOException
	 */
	private boolean judeSessionUserMall(HttpServletResponse response, ThirdSession thirdSession) throws IOException {
		String userId = thirdSession.getUserId();
		if(StrUtil.isBlank(userId)){
			this.writerPrint(response, "请先登录");
			return Boolean.FALSE;
		}
		return Boolean.TRUE;
	}

	private void writerPrint(HttpServletResponse response, String msg) throws IOException {
		//返回401错误码，触发小程序重新登录
		JwtUtil.responseError(response,401,msg);
	}
}
